import { http } from '@libs/common/request';
import { getConfig } from '@libs/common/utils';

import { agentId } from './config';

const { DD } = getConfig();

interface BaseResult {
  errcode: number;
  errmsg: string;
}

export interface IDingToken extends BaseResult {
  access_token: string;
  /** access_token的过期时间，单位秒。 */
  expires_in: number;
}

export const ApiDDGetAccessToken = async () => {
  const appkey = DD.DD_AppKey;
  const appsecret = DD.DD_AppSecret;
  const api = 'https://oapi.dingtalk.com/gettoken';
  const body = { appkey, appsecret };
  const res = await http.get<IDingToken>(api, body);
  if (res.data.errcode === 0) {
    return res.data;
  } else {
    throw new Error(res.data.errmsg);
  }
};

export interface IDingUserInfo extends BaseResult {
  result: {
    associated_unionid: string;
    unionid: string;
    device_id: string;
    sys_level: number;
    name: string;
    sys: boolean;
    userid: string;
  };
}

export const ApiDDGetUserInfo = async (access_token: string, code: string) => {
  const api = `https://oapi.dingtalk.com/topapi/v2/user/getuserinfo?access_token=${access_token}`;

  const res = await http.get<IDingUserInfo>(
    api,
    { code },
    { scid: undefined, Authorization: undefined },
  );

  if (res.data.errcode === 0) {
    return res.data.result;
  } else {
    throw new Error(res.data.errmsg);
  }
};

interface AccessToken {
  access_token: string;
}

export interface AttendanceListParams extends AccessToken {
  userIdList: string[];
  /** 查询考勤打卡记录的起始工作日 */
  workDateFrom?: string;
  /** 查询考勤打卡记录的结束工作日 */
  workDateTo?: string;
  /** 表示获取考勤数据的条数，最大值50。 */
  offset?: number;
  /** 表示获取考勤数据的起始点。第一次传0 */
  limit?: number;
}

export interface ResAttendanceList extends BaseResult {
  hasMore: boolean;
  recordresult: Recordresult[];
}

export interface Recordresult {
  checkType: string;
  corpId: string;
  locationResult: string;
  baseCheckTime: number;
  groupId: number;
  timeResult: string;
  userId: string;
  recordId?: number;
  workDate: number;
  sourceType: string;
  userCheckTime: number;
  planId: number;
  id: number;
}

/**
 * 获取打卡结果
 * @link https://open.dingtalk.com/document/isvapp/open-attendance-clock-in-data
 */
export const ApiDDAttendanceList = async (
  param: AttendanceListParams,
): Promise<ResAttendanceList['recordresult']> => {
  let num = 0;
  const {
    access_token,
    workDateFrom,
    workDateTo,
    userIdList,
    offset = 0,
    limit = 50,
  } = param;

  // mock 数据
  // const mock = await MockAttendanceList();
  // return mock as unknown as ResAttendanceList['recordresult'];

  const api =
    'https://oapi.dingtalk.com/attendance/list?access_token=' + access_token;

  const list: Recordresult[] = [];
  let hasMore = true;
  let page = offset;

  while (hasMore) {
    const { data } = await http.post<ResAttendanceList>(api, {
      workDateFrom: workDateFrom || '',
      workDateTo: workDateTo || '',
      userIdList,
      offset: page,
      limit,
    });
    console.log('num :>> ', num);
    if (num++ > 50) break;

    hasMore = data.hasMore;
    console.log('hasMore :>> ', hasMore);
    page += limit;
    console.log('page :>> ', page);

    if (data.errcode === 0) {
      list.push(...data.recordresult);
    } else {
      throw new Error(data.errmsg);
    }
  }

  return list;
};

export interface ResGetColumnVal extends BaseResult {
  result: { column_vals: Columnval2[] };
  request_id: string;
}

export interface Columnval2 {
  column_vals: Columnval[];
  column_vo: Columnvo;
}

export interface Columnvo {
  id: number;
}

export interface Columnval {
  date: string;
  value: string;
}
export interface GetColumnValParams extends AccessToken {
  userid: string;
  /** 报表列ID，多值用英文逗号分隔，最大长度20 */
  column_id_list: string;
  /** 开始时间。 */
  from_date: string;
  /** 结束时间，结束时间减去开始时间必须在31天以内。 */
  to_date: string;
}

/**
 * 获取报表列值
 * @description 不支持获取离职人员的考勤信息，离职人员的考勤数据可以在OA管理后台查询。
 * @description 本接口获取应出勤天数字段值，只支持获取距今15天内的应出勤天数value值，超过15天后的应出勤天数value值为0。
 * @see [column_id_list](../../attendance-statistics/entities/attendance-statistic.entity.ts) 说明
 * @link https://open.dingtalk.com/document/isvapp/obtains-the-column-values-of-the-smart-attendance-report
 */
export const ApiDDGetColumnVal = async (
  param: GetColumnValParams,
): Promise<ResGetColumnVal['result']> => {
  const { access_token, userid, column_id_list, from_date, to_date } = param;

  const api =
    'https://oapi.dingtalk.com/topapi/attendance/getcolumnval?access_token=' +
    access_token;

  const { data } = await http.post<ResGetColumnVal>(api, {
    userid,
    column_id_list,
    from_date,
    to_date,
  });

  if (data.errcode === 0) {
    return data.result;
  } else {
    throw new Error(data.errmsg);
  }
};

interface ResCorpConversationMessage {
  access_token: string;
  userDingId: string;
  context: Record<string, any>;
}

/**
 *
 * 发送工作通知消息
 * @link https://open.dingtalk.com/document/isvapp/send-job-notification
 */
export const ApiDDCorpConversationMessage = async (
  param: ResCorpConversationMessage,
) => {
  const { access_token, userDingId, context } = param;

  const api =
    'https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=' +
    access_token;

  const { data } = await http.post<any>(
    api,
    {
      agent_id: agentId,
      userid_list: userDingId,
      msg: context,
    },
    {
      Authorization: undefined,
      scid: undefined,
    },
  );

  if (data.errcode !== 0) {
    throw new Error(data.errmsg);
  }
};

/**
 *
 * 钉钉机器人发送消息
 * @link https://open.dingtalk.com/document/isvapp/custom-bot-access-send-message
 */
export const ApiDDRobotSend = async (param: {
  access_token: string;
  context: Record<string, any>;
}) => {
  const { access_token, context } = param;
  const api =
    'https://oapi.dingtalk.com/robot/send?access_token=' + access_token;

  const { data } = await http.post<any>(api, context, {
    Authorization: undefined,
    scid: undefined,
  });

  if (data.errcode !== 0) {
    throw new Error(data.errmsg);
  }
};
